package com.bdmc.device.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bdmc.common.core.domain.PageQuery;
import com.bdmc.common.core.mybatisplus.core.ServicePlusImpl;
import com.bdmc.common.core.page.TableDataInfo;
import com.bdmc.common.utils.MapDistance;
import com.bdmc.common.utils.StringUtils;
import com.bdmc.device.domain.DevGpsHistory;
import com.bdmc.device.domain.bo.DevGpsHistoryBo;
import com.bdmc.device.domain.vo.DevGpsHistoryVo;
import com.bdmc.device.mapper.DevGpsHistoryMapper;
import com.bdmc.device.service.IDevGpsHistoryService;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * GPS设备历史数据Service业务层处理
 *
 * @author bdmc
 * @date 2022-03-22
 */
@Service
public class DevGpsHistoryServiceImpl extends ServicePlusImpl<DevGpsHistoryMapper, DevGpsHistory, DevGpsHistoryVo> implements IDevGpsHistoryService {

    @Override
    public DevGpsHistoryVo queryById(Integer historyId){
        return getVoById(historyId);
    }

    @Override
    public TableDataInfo<DevGpsHistoryVo> queryPageList(DevGpsHistoryBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<DevGpsHistory> lqw = buildQueryWrapper(bo);
        Page<DevGpsHistoryVo> result = pageVo(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<DevGpsHistoryVo> mySelectPage(DevGpsHistoryBo bo, PageQuery pageQuery) {
        return TableDataInfo.build(baseMapper.mySelectPage(pageQuery.build(),bo));
    }

    @Override
    public List<DevGpsHistoryVo> queryList(DevGpsHistoryBo bo) {
        LambdaQueryWrapper<DevGpsHistory> lqw = buildQueryWrapper(bo);
        return listVo(lqw);
    }

    private LambdaQueryWrapper<DevGpsHistory> buildQueryWrapper(DevGpsHistoryBo bo) {
        LambdaQueryWrapper<DevGpsHistory> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getDeviceId() != null, DevGpsHistory::getDeviceId, bo.getDeviceId());
        lqw.eq(StringUtils.isNotBlank(bo.getLat()), DevGpsHistory::getLat, bo.getLat());
        lqw.eq(StringUtils.isNotBlank(bo.getLng()), DevGpsHistory::getLng, bo.getLng());
        lqw.eq(bo.getDataTime() != null, DevGpsHistory::getDataTime, bo.getDataTime());
        lqw.eq(bo.getAlarmCode() != null, DevGpsHistory::getAlarmCode, bo.getAlarmCode());
        lqw.eq(StringUtils.isNotBlank(bo.getAlarmType()), DevGpsHistory::getAlarmType, bo.getAlarmType());
        lqw.eq(bo.getHight() != null, DevGpsHistory::getHight, bo.getHight());
        lqw.eq(bo.getSpeed() != null, DevGpsHistory::getSpeed, bo.getSpeed());
        lqw.eq(bo.getDirection() != null, DevGpsHistory::getDirection, bo.getDirection());
        lqw.eq(bo.getMileage() != null, DevGpsHistory::getMileage, bo.getMileage());
        lqw.eq(StringUtils.isNotBlank(bo.getOilMass()), DevGpsHistory::getOilMass, bo.getOilMass());
        lqw.eq(bo.getVoltageLevel() != null, DevGpsHistory::getVoltageLevel, bo.getVoltageLevel());
        lqw.eq(bo.getGsmSignal() != null, DevGpsHistory::getGsmSignal, bo.getGsmSignal());
        lqw.eq(StringUtils.isNotBlank(bo.getDevState()), DevGpsHistory::getDevState, bo.getDevState());
        lqw.eq(StringUtils.isNotBlank(bo.getCarLocation()), DevGpsHistory::getCarLocation, bo.getCarLocation());
        //lqw.eq(bo.getCreateDate() != null, DevGpsHistory::getCreateDate, bo.getCreateDate());
        return lqw;
    }

    @Override
    public Boolean insertByBo(DevGpsHistoryBo bo) {
        DevGpsHistory add = BeanUtil.toBean(bo, DevGpsHistory.class);
        validEntityBeforeSave(add);
        boolean flag = save(add);
        if (flag) {
            bo.setHistoryId(add.getHistoryId());
        }
        return flag;
    }

    @Override
    public Boolean updateByBo(DevGpsHistoryBo bo) {
        DevGpsHistory update = BeanUtil.toBean(bo, DevGpsHistory.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(DevGpsHistory entity){
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Integer> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }

    @Override
    public List<DevGpsHistoryVo> traceList(DevGpsHistoryBo bo) {
        List<DevGpsHistoryVo> historyVos = baseMapper.traceList(bo);
        boolean isStop = false;
        //boolean endStop = false;
        double mile = 0;
        DevGpsHistoryVo startStopPoint = null;
        for (int i = 0; i < historyVos.size(); i++) {

            historyVos.get(i).setTargetName(bo.getTargetName());
            if (i == historyVos.size() - 1) {
                //最后一条数据
                if (isStop) {
                    Long minute = calcMinute(startStopPoint.getDataTime(), historyVos.get(i).getDataTime());
                    historyVos.get(i).setStopMinute(minute);
                }
                break;
            }

            DevGpsHistoryVo first = historyVos.get(i);
            if (i == 0) first.setCalcMile("0.000");
            DevGpsHistoryVo second = historyVos.get(i + 1);
            double distance = MapDistance.getDistance(first.getLat(), first.getLng(), second.getLat(), second.getLng());
            mile += distance;
            second.setCalcMile(String.format("%.3f", mile));
            if (distance < 0.1d) {
                isStop = true;
                if (startStopPoint == null)
                    startStopPoint = first;
            } else {
                if (isStop) {
                    Long minute = calcMinute(startStopPoint.getDataTime(), second.getDataTime());
                    second.setStopMinute(minute);
                }
                startStopPoint = null;
                isStop = false;
            }

            if(historyVos.get(i).getStopMinute()==null){
                historyVos.get(i).setStopMinute(0L);
            }
        }
        return historyVos;
    }

    @Override
    public Map<String, Object> carMileage(DevGpsHistoryBo bo) {
        return  baseMapper.carMileage(bo);
    }
    @Override
    public Integer insertData(DevGpsHistoryBo bo) {
        return  baseMapper.insertData(bo);
    }

    /**
     * 计算2个时间的相差分钟
     *
     * @param startTime 第一个时间
     * @param endTime 第二个时间
     * @return 相差分钟
     */
    private Long calcMinute(String startTime, String endTime) {
        LocalDateTime firstDate = LocalDateTimeUtil.parse(startTime.substring(0, 19), DatePattern.NORM_DATETIME_FORMATTER);
        LocalDateTime secondDate = LocalDateTimeUtil.parse(endTime.substring(0, 19), DatePattern.NORM_DATETIME_FORMATTER);
        long intervalSecond = secondDate.toEpochSecond(OffsetDateTime.now().getOffset()) - firstDate.toEpochSecond(OffsetDateTime.now().getOffset());
        return intervalSecond / 60;
    }
}
